package com.bwie.service.impl;

import com.bwie.pojo.DriverLocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DriverGeoService {

    private static final String DRIVER_KEY = "driver";

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 添加司机位置
     */
    public void addDriverLocation(DriverLocation driver) {
        redisTemplate.opsForGeo().add(
                DRIVER_KEY,
                new RedisGeoCommands.GeoLocation<>(
                        driver.getDriverId(),
                        new Point(driver.getLongitude(), driver.getLatitude())
                )
        );
    }

    /**
     * 查找指定坐标附近的司机
     * @param longitude 经度
     * @param latitude 纬度
     * @param radiusKm 半径（公里）
     * @param count 最多返回数量
     */
    public List<GeoResult<RedisGeoCommands.GeoLocation<String>>> findNearbyDrivers(
            double longitude, double latitude, double radiusKm, long count) {

        Circle circle = new Circle(new Point(longitude, latitude), new Distance(radiusKm, Metrics.KILOMETERS));

        GeoResults<RedisGeoCommands.GeoLocation<String>> results =
                redisTemplate.opsForGeo().radius(DRIVER_KEY, circle,
                        RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                                .includeDistance()  // 返回距离
                                .includeCoordinates() // 返回坐标
                                .sortAscending()     // 按距离升序
                                .limit(count)        // 限制返回数量
                );

        return results.getContent();
    }

    /**
     * 计算两个司机之间的距离（km）
     */
    public double getDistance(String driver1, String driver2) {
        Distance distance = redisTemplate.opsForGeo().distance(DRIVER_KEY, driver1, driver2, Metrics.KILOMETERS);
        return distance != null ? distance.getValue() : -1;
    }
}